﻿using System.Collections.Generic;
using Entities;
using System.ComponentModel.Composition;
using System.Linq;
using DAL;

namespace Services
{
    [Export(typeof(IBotService))]
    public class BotService : IBotService
    {
        #region Member Variables

        readonly IUnitOfWork _uow;

        #endregion

        #region Constructor

        [ImportingConstructorAttribute]
        public BotService(IUnitOfWork uow)
        {
            this._uow = uow;
        }

        #endregion

        #region IBotService

        IDictionary<string, string> IBotService.ValidateUnusualActivityData(BOT bot)
        {
            var validationDictionary = new Dictionary<string, string>();

            if (bot.BotType == (int)BotType.UnusualActivity)
            {
                if (!bot.UnusualTrainingSpan.HasValue)
                {
                    validationDictionary.Add("UnusualTrainingSpan", Resources.UnusualTrainingSpanErrorMsg);
                }

                if (!bot.UnusualTrainingValue.HasValue)
                {
                    validationDictionary.Add("UnusualTrainingValue", Resources.UnusualTrainingValueErrorMsg);
                }
            }

            return validationDictionary;
        }

        IDictionary<string, string> IBotService.ValidateBotFilterStep(BOT bot)
        {
            var validationDictionary = new Dictionary<string, string>();

            if (!bot.AllHours && !bot.BotPeriodHours.Any())
            {
                validationDictionary.Add("PeriodHours", Resources.PeriodHoursErrorMsg);
            }

            return validationDictionary;
        }

        IDictionary<string, string> IBotService.ValidateBotOperationsStep(IEnumerable<string> selectedOperations, bool isAllOperations)
        {
            var validationDictionary = new Dictionary<string, string>();

            if (!isAllOperations && (selectedOperations == null || selectedOperations.Count() == 0))
            {
                validationDictionary.Add("Operations", Resources.OperationsErrorMsg);
            }

            return validationDictionary;
        }

        IDictionary<string, string> IBotService.ValidateUsersMachinesStep(BOT bot)
        {
            var result = new Dictionary<string, string>();

            if (!bot.AllUsers && !bot.BotsUsers.Any())
            {
                result.Add("SelectedUsers", Resources.SelectedUsersErrorMsg);
            }

            if (!bot.AllMachines && !bot.BotsMachines.Any())
            {
                result.Add("SelectedMachines", Resources.SelectedMachinesErrorMsg);
            }

            return result;
        }

        IDictionary<string, string> IBotService.ValidateRecepientsStep(BOT bot)
        {
            var result = new Dictionary<string, string>();

            if (!bot.BotRecipients.Any())
            {
                result.Add("", Resources.BotRecipientsErrorMsg);
            }

            return result;
        }

        BOT IBotService.EditBot(int id)
        {
            return GetBot(id);
        }

        BOT IBotService.DisplayBot(int id)
        {
            BOT bot = GetBot(id);

            foreach (var item in bot.BotsOperations)
            {
                item.Operation = _uow.OperationRepository.Single(b => b.OperationID == item.OperationId);
            }

            return bot;
        }

        void IBotService.SaveBot(BOT bot)
        {
            if (bot.AllUsers)
            {
                bot.BotsUsers = new TrackableCollection<BotsUser>();
            }
            if (bot.AllMachines)
            {
                bot.BotsMachines = new TrackableCollection<BotsMachine>();
            }

            if (bot.BotId == 0)
            {
                _uow.BOTRepository.Add(bot);
            }
            else
            {
                var recepients = _uow.BotRecipientRepository.Find(b => b.BotId == bot.BotId);
                foreach (var recepient in recepients)
                {
                    _uow.BotRecipientRepository.Delete(recepient);
                }

                var machines = _uow.BotsMachineRepository.Find(b => b.BotId == bot.BotId);
                foreach (var machine in machines)
                {
                    _uow.BotsMachineRepository.Delete(machine);
                }

                var users = _uow.BotsUserRepository.Find(b => b.BotId == bot.BotId);
                foreach (var user in users)
                {
                    _uow.BotsUserRepository.Delete(user);
                }

                var hours = _uow.BotPeriodHourRepository.Find(b => b.BotId == bot.BotId);
                foreach (var hour in hours)
                {
                    _uow.BotPeriodHourRepository.Delete(hour);
                }

                var operations = _uow.BotsOperationRepository.Find(b => b.BotId == bot.BotId);
                foreach (var operation in operations)
                {
                    _uow.BotsOperationRepository.Delete(operation);
                }

                foreach (var recepient in bot.BotRecipients)
                {
                    recepient.BotId = bot.BotId;
                    _uow.BotRecipientRepository.Add(recepient);
                }

                foreach (var user in bot.BotsUsers)
                {
                    user.BotId = bot.BotId;
                    _uow.BotsUserRepository.Add(user);
                }

                foreach (var machine in bot.BotsMachines)
                {
                    machine.BotId = bot.BotId;
                    _uow.BotsMachineRepository.Add(machine);
                }

                foreach (var operation in bot.BotsOperations)
                {
                    operation.BotId = bot.BotId;
                    _uow.BotsOperationRepository.Add(operation);
                }

                foreach (var hour in bot.BotPeriodHours)
                {
                    hour.BotId = bot.BotId;
                    _uow.BotPeriodHourRepository.Add(hour);
                }

                _uow.BOTRepository.Update(bot);
            }

            _uow.Commit();
        }

        void IBotService.Delete(int id)
        {
            var bot = _uow.BOTRepository.Single(b => b.BotId == id);
            _uow.BOTRepository.Delete(bot);
            _uow.Commit();
        }

        #endregion

        #region Private Methods

        private BOT GetBot(int id)
        {
            BOT bot = _uow.BOTRepository.Single(b => b.BotId == id);

            var users = _uow.BotsUserRepository.Find(u => u.BotId == id);
            foreach (var user in users)
            {
                bot.BotsUsers.Add(user);
            }

            var machines = _uow.BotsMachineRepository.Find(u => u.BotId == id);
            foreach (var machine in machines)
            {
                bot.BotsMachines.Add(machine);
            }

            var recepients = _uow.BotRecipientRepository.Find(u => u.BotId == id);
            foreach (var recepient in recepients)
            {
                bot.BotRecipients.Add(recepient);
            }

            var periodHours = _uow.BotPeriodHourRepository.Find(h => h.BotId == id);
            foreach (var hour in periodHours)
            {
                bot.BotPeriodHours.Add(hour);
            }

            bot.BotsOperations = new TrackableCollection<BotsOperation>();
            var botsOperations = _uow.BotsOperationRepository.Find(o => o.BotId == id);

            foreach (BotsOperation botsOperation in botsOperations)
            {
                bot.BotsOperations.Add(botsOperation);
            }

            return bot;
        }

        #endregion


        IDictionary<string, string> IBotService.ValidateScheduleStep(BOT bot, int? endPeriodHour)
        {
            //TODO:test this
            var validationDictionary = new Dictionary<string, string>();

            if (bot.EndPeriod.HasValue)
            {
                if (!endPeriodHour.HasValue)
                {
                    validationDictionary["EndPeriodHour"] = "Please enter endPeriodHour";
                }

                if (bot.EndPeriod < bot.StartPeriod)
                {
                    validationDictionary["EndPeriod"] = "Please enter correct dates";
                }
            }

            return validationDictionary;
        }
    }
}